'use strict'

const titbit = require('titbit');
const fs = require('fs');
const dbcfg = require('./dbconfig');
const pg = require('pg');
const { request } = require('https');
const wxkey = require('./wxkey');
const {httpcli} = require('gohttp');
const token = require('titbit-token');
const tbloader = require('titbit-loader')
// 对于一个程序来说，知道其运行位置并在其运行位置上扩展是非常重要的
// 如果改变运行路径会导致images文件夹创建在错误的位置，所以需要在开始时切换工作目录
process.chdir(__dirname);

try {
    fs.accessSync('./images');
} catch (err) {
    fs.mkdirSync('./images');
}


let psql = new pg.Pool(dbcfg);


let cert_path = '/usr/local/share';
const app = new titbit({
    // 开启调试模式，若有错误会输出错误信息
    debug : true,
    globalLog:true,
    cert: `${cert_path}/api.jinjin.work.pem`,
    key:`${cert_path}/api.jinjin.work.key`
})


let tb = new tbloader();
tb.init(app);
app.addService('psql',psql);// 项目在运行时会有一个app.service，它是一个空对象，可以放任何东西，app.addService就是往里面添加一个属性并将那个属性值赋给它，每一个新的实例中的service都会指向app.service，也就可以去拿到里面的属性
app.addService('imagePath',`${__dirname}/images`)
// 添加路由
// app.get("/",async c => {//c就是请求上下文
//     c.send('OK!')
// })

// app.get('/upload',async c => {
//     // c.reply是响应对象，可写的流，
//     // 在HTTP/1.1中c.reply指向response；在HTTP/2中c.reply指向http2stream
//     await c.helper.pipe('./httphandleprogram/upload.html',c.reply)//请求模块里有一个helper模块，提供很多工具，比如生成唯一id等等
    
    
// })
// app.get('/randimg', async c => {//随机返回一张图片
//     fs.readdir('./images' ,(e,files) =>{
//         if (e) {
//             c.send(e)
//         }
//         else {
//             let i = parseInt(Math.random()*files.length);//应返回一个图片的数据
//             c.send(files[i]);
//         }
//     })
// })


let tok = new token({
    // token有效期，单位为秒
    expires:45,
    //必须是32位字符
    // key就是加解密的秘钥，相当于密码
    key:'abcdefghijklmnopqrstuvwxyzkutaha',

    // 必须是16位字符
    // iv就是作为初始干扰的数据，底层需要用它进行与或操作
    iv:'qwertyuiopasdfgh'
})



app.addService('tok',tok);

app.get('/mp-login/:code', async c => {
    let auth_url = 'https://api.weixin.qq.com/sns/jscode2session'
                +`?appid=${wxkey.appid}`
                +`&secret=${wxkey.secret}`
                +`&js_code=${c.param.code}`
                +`&grant_type=authorization_code`;
    let ret = await httpcli.get(auth_url)
                            .then(res => {
                                return res.json();
                            })
    c.send(tok.make(ret));
    
})

app.get('/decrypt/:token',async c=> {
    c.send(tok.verify(c.param.token));
})

// *在这个框架中表示任意字符
// app.get('/static/*',callback)

// 运行在6001端口
app.run(6001);

/**
 * HTTP消息头content-type指定了数据的类型（数据的格式）。
 * 
 * Client                                                           Server
 *    content-type描述的值要和提交的Body数据格式一致。                   根据content-type的值决定如何解析Body数据。
 * 
 * content-type:
 *      multipart/form-data;boundary=xxx  -----   文件解析
 *      text/*    -----------------------------   文本类型
 *      application/*   -----------------------   要看具体值，application/json也是文本类型
 *      ......   ------------------------------   每种类型如何处理是双方设计好的通信方式
 * 
 * 到Web连框架这一层面，则如何处理是开发框架设计好的，但通常都要遵循一个原则：
 *         允许开发者做自己的处理。
 * 
 * 在本框架范围内：
 *      multipart类型  c.body是object类型，文件信息解析到c.files。
 *      application/x-www-form-urlencoded  传统的表单类，c.body是object类型，用于获取提交的表单数据。
 *      text/*  c.body是文本类型，c.body = c.rawBody.toString('utf-8')
 *      其他类型：  c.body是buffer类型，就是对c.rawBody的引用。
 */